/*
Filename: BROWSER.H
Description: Defines an interface for a web browser control, including event sinking.
Date: 08/09/2003

Copyright (c) 2003 by Gilad Novik.  (Web: http://gilad.gsetup.com, Email: gilad@gsetup.com)
All rights reserved.

Copyright / Usage Details
-------------------------
You are allowed to include the source code in any product (commercial, shareware, freeware or otherwise)
when your product is released in binary form. You are allowed to modify the source code in any way you want
except you cannot modify the copyright details at the top of the module. If you want to distribute source
code with your application, then you are only allowed to distribute versions released by the author. This is
to maintain a single distribution point for the source code.
*/

#ifndef _BROWSER_H
#define _BROWSER_H

#include <ExDispid.h>
#include <ComDef.h>
#include <mshtml.h>
#include <MsHtmcid.h>
#include "HtmlEvents.h"


typedef  VOID (*MOUSE_EVENT_HANDLER)();

class CWebBrowser2EventsBase
{
protected:
	static _ATL_FUNC_INFO StatusTextChangeStruct;
	static _ATL_FUNC_INFO TitleChangeStruct;
	static _ATL_FUNC_INFO PropertyChangeStruct;
	static _ATL_FUNC_INFO OnQuitStruct;
	static _ATL_FUNC_INFO OnToolBarStruct;
	static _ATL_FUNC_INFO OnMenuBarStruct;
	static _ATL_FUNC_INFO OnStatusBarStruct;
	static _ATL_FUNC_INFO OnFullScreenStruct;
	static _ATL_FUNC_INFO OnTheaterModeStruct;
	static _ATL_FUNC_INFO DownloadBeginStruct;
	static _ATL_FUNC_INFO DownloadCompleteStruct;
	static _ATL_FUNC_INFO NewWindow2Struct; 
	static _ATL_FUNC_INFO CommandStateChangeStruct;
	static _ATL_FUNC_INFO BeforeNavigate2Struct;
	static _ATL_FUNC_INFO ProgressChangeStruct;
	static _ATL_FUNC_INFO NavigateComplete2Struct;
	static _ATL_FUNC_INFO DocumentComplete2Struct;
	static _ATL_FUNC_INFO OnVisibleStruct;
	static _ATL_FUNC_INFO SetSecureLockIconStruct;
	static _ATL_FUNC_INFO NavigateErrorStruct;
	static _ATL_FUNC_INFO PrivacyImpactedStateChangeStruct;
	//static _ATL_FUNC_INFO FileDownloadStruct;   // Unsafe to use
	//static _ATL_FUNC_INFO WindowClosingStruct;
};
template<class T,UINT nID=0>
class CWebBrowser2 :   public CWebBrowser2EventsBase , public IDispEventSimpleImpl<nID, CWebBrowser2<T>, &DIID_DWebBrowserEvents2>
{
	typedef CWebBrowser2<T, nID> thisClass;
//	typedef CString CString;

public:
	enum RefreshConstants
	{
		REFRESH_NORMAL = 0,
		REFRESH_IFEXPIRED = 1,
		REFRESH_CONTINUE = 2,
		REFRESH_COMPLETELY = 3
	};
	
	BEGIN_MSG_MAP(thisClass)
		MESSAGE_HANDLER(WM_CREATE, OnCreate)
		MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
	END_MSG_MAP()
		
	BEGIN_SINK_MAP(thisClass)
		SINK_ENTRY_INFO(nID, DIID_DWebBrowserEvents2, DISPID_STATUSTEXTCHANGE, __StatusTextChange, &StatusTextChangeStruct)
		SINK_ENTRY_INFO(nID, DIID_DWebBrowserEvents2, DISPID_PROGRESSCHANGE, __ProgressChange, &ProgressChangeStruct)
		SINK_ENTRY_INFO(nID, DIID_DWebBrowserEvents2, DISPID_COMMANDSTATECHANGE, __CommandStateChange, &CommandStateChangeStruct)
		SINK_ENTRY_INFO(nID, DIID_DWebBrowserEvents2, DISPID_DOWNLOADBEGIN, __DownloadBegin, &DownloadBeginStruct)
		SINK_ENTRY_INFO(nID, DIID_DWebBrowserEvents2, DISPID_DOWNLOADCOMPLETE, __DownloadComplete, &DownloadCompleteStruct)
		SINK_ENTRY_INFO(nID, DIID_DWebBrowserEvents2, DISPID_TITLECHANGE, __TitleChange, &TitleChangeStruct)
		SINK_ENTRY_INFO(nID, DIID_DWebBrowserEvents2, DISPID_NAVIGATECOMPLETE2, __NavigateComplete2, &NavigateComplete2Struct)
		SINK_ENTRY_INFO(nID, DIID_DWebBrowserEvents2, DISPID_BEFORENAVIGATE2, __BeforeNavigate2, &BeforeNavigate2Struct)
		SINK_ENTRY_INFO(nID, DIID_DWebBrowserEvents2, DISPID_PROPERTYCHANGE, __PropertyChange, &PropertyChangeStruct)
		SINK_ENTRY_INFO(nID, DIID_DWebBrowserEvents2, DISPID_NEWWINDOW2, __NewWindow2, &NewWindow2Struct)
		SINK_ENTRY_INFO(nID, DIID_DWebBrowserEvents2, DISPID_DOCUMENTCOMPLETE, __DocumentComplete, &DocumentComplete2Struct)
		SINK_ENTRY_INFO(nID, DIID_DWebBrowserEvents2, DISPID_ONQUIT, __OnQuit, &OnQuitStruct)
		SINK_ENTRY_INFO(nID, DIID_DWebBrowserEvents2, DISPID_ONVISIBLE, __OnVisible, &OnVisibleStruct)
		SINK_ENTRY_INFO(nID, DIID_DWebBrowserEvents2, DISPID_ONTOOLBAR, __OnToolBar, &OnToolBarStruct)
		SINK_ENTRY_INFO(nID, DIID_DWebBrowserEvents2, DISPID_ONMENUBAR, __OnMenuBar, &OnMenuBarStruct)
		SINK_ENTRY_INFO(nID, DIID_DWebBrowserEvents2, DISPID_ONSTATUSBAR, __OnStatusBar, &OnStatusBarStruct)
		SINK_ENTRY_INFO(nID, DIID_DWebBrowserEvents2, DISPID_ONFULLSCREEN, __OnFullScreen, &OnFullScreenStruct)
		SINK_ENTRY_INFO(nID, DIID_DWebBrowserEvents2, DISPID_ONTHEATERMODE, __OnTheaterMode, &OnTheaterModeStruct)
		SINK_ENTRY_INFO(nID, DIID_DWebBrowserEvents2, DISPID_SETSECURELOCKICON, __SetSecureLockIcon, &SetSecureLockIconStruct)
		SINK_ENTRY_INFO(nID, DIID_DWebBrowserEvents2, DISPID_NAVIGATEERROR, __NavigateError, &NavigateErrorStruct)
		SINK_ENTRY_INFO(nID, DIID_DWebBrowserEvents2, DISPID_PRIVACYIMPACTEDSTATECHANGE, __PrivacyImpactedStateChange, &PrivacyImpactedStateChangeStruct)
		//SINK_ENTRY_INFO(nID, DIID_DWebBrowserEvents2, DISPID_WINDOWCLOSING, __WindowClosing, &WindowClosingStruct)
		//SINK_ENTRY_INFO(nID, DIID_DWebBrowserEvents2, DISPID_FILEDOWNLOAD, __FileDownload, &FileDownloadStruct)
	END_SINK_MAP()
		
	CWebBrowser2()
	{
		pMouseUp = NULL;
		m_bState[back]=m_bState[forward]=FALSE;
	}
	
	LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
	{
		T* pT = static_cast<T*>(this);
		LRESULT lResult=pT->DefWindowProc();
		HRESULT hResult=pT->QueryControl(IID_IWebBrowser2, (void**)&m_pBrowser);
		if (SUCCEEDED(hResult))
		{
			if (FAILED(DispEventAdvise(m_pBrowser,&DIID_DWebBrowserEvents2)))
			{
				ATLASSERT(FALSE);
				m_pBrowser.Release();
			}
		}
		
		return lResult;
	}
	//static MOUSE_EVENT_HANDLER m_MouseUp;

	LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
	{
		if(pMouseUp)
		{
			IHTMLDocument3* pHtmlDoc3 = GetHtmlDocument3();
			BSTR bsMouseMoveEvent = ::SysAllocString(L"onmouseup");
			pHtmlDoc3->detachEvent(bsMouseMoveEvent,pMouseUp);
			::SysFreeString(bsMouseMoveEvent);
			delete pMouseUp;
			pMouseUp = NULL;
		}
		if (m_pBrowser)
		{
			DispEventUnadvise(m_pBrowser, &DIID_DWebBrowserEvents2);
			m_pBrowser.Release();
		}
		bHandled=FALSE;
		
		return 0;
	}
	
	void OnSetSecureLockIcon(long nSecureLockIcon) { }
	BOOL OnNavigateError(IDispatch* pDisp, const CString& szURL, const CString& szTargetFrameName, LONG nStatusCode)
	{   // Return TRUE to cancel
		return TRUE;
	}
	void OnPrivacyImpactedStateChange(BOOL bImpacted) { }
	void OnStatusTextChange(const CString& szText) { }
	void OnProgressChange(long nProgress, long nProgressMax) { }
	void OnCommandStateChange(long nCommand, BOOL bEnable)
	{
		switch (nCommand)
		{
		case CSC_NAVIGATEBACK:
			m_bState[back]=bEnable;
			break;
		case CSC_NAVIGATEFORWARD:
			m_bState[forward]=bEnable;
			break;
		}
	}
	void OnDownloadBegin() { }
	void OnDownloadComplete() { }
	void OnTitleChange(const CString& szTitle) { }
	void OnNavigateComplete2(IDispatch* pDisp, const CString& szURL) { }
	BOOL OnBeforeNavigate2(IDispatch* pDisp, const CString& szURL, DWORD dwFlags, const CString& szTargetFrameName, CSimpleArray<BYTE>& pPostedData, const CString& szHeaders)
	{   // Return TRUE to cancel
		return FALSE;
	}
	void OnPropertyChange(const CString& szProperty) { }
	BOOL OnNewWindow2(IDispatch** ppDisp)
	{   // Return TRUE to cancel
		return FALSE;
	}
	LPDISPATCH pMouseUp ;
	void OnDocumentComplete(IDispatch* pDisp, const CString& szURL) 
	{ 
		if(pMouseUp)
		{
			IHTMLDocument3* pHtmlDoc3 = GetHtmlDocument3();
			BSTR bsMouseMoveEvent = ::SysAllocString(L"onmouseup");
			pHtmlDoc3->detachEvent(bsMouseMoveEvent,pMouseUp);
			::SysFreeString(bsMouseMoveEvent);
			delete pMouseUp;
			pMouseUp = NULL;
		}
		IHTMLDocument3* pHtmlDoc3 = GetHtmlDocument3();
		 BSTR bsMouseMoveEvent = ::SysAllocString(L"onmouseup");
		 pMouseUp =CHtmlEvents::CreateEventObject( (EVENT_FUNCTION) OnMouseUp, 0, this );
		 pHtmlDoc3->attachEvent(bsMouseMoveEvent,pMouseUp,FALSE);
		::SysFreeString(bsMouseMoveEvent);
	}
	void OnQuit() { 
		
	}
	void OnVisible(BOOL bVisible) { }
	void OnToolBar(BOOL bToolBar) { }
	void OnMenuBar(BOOL bMenuBar) { }
	void OnStatusBar(BOOL bStatusBar) { }
	void OnFullScreen(BOOL bFullScreen) { }
	void OnTheaterMode(BOOL bTheaterMode) { }
	/*
	BOOL OnWindowClosing(BOOL bChildWindow)
	{   // Return TRUE to cancel
		return FALSE;
	}
	*/
	/*
	BOOL OnFileDownload()
	{   // Return TRUE to cancel
		return FALSE;
	}
	*/
	
	// Properties
	__declspec(property(get=GetAddressBar,put=PutAddressBar)) BOOL AddressBar;
	__declspec(property(get=GetApplication)) IDispatchPtr Application;
	__declspec(property(get=GetBusy)) BOOL Busy;
	__declspec(property(get=GetFullName)) CString FullName;
	__declspec(property(get=GetLocationName)) CString LocationName;
	__declspec(property(get=GetLocationURL)) CString LocationURL;
	__declspec(property(get=GetRegisterAsBrowser,put=PutRegisterAsBrowser)) BOOL RegisterAsBrowser;
	__declspec(property(get=GetRegisterAsDropTarget,put=PutRegisterAsDropTarget)) BOOL RegisterAsDropTarget;
	__declspec(property(get=GetTheaterMode,put=PutTheaterMode)) BOOL TheaterMode;
	__declspec(property(get=GetVisible,put=PutVisible)) BOOL Visible;
	__declspec(property(get=GetMenuBar,put=PutMenuBar)) BOOL MenuBar;
	__declspec(property(get=GetToolBar,put=PutToolBar)) BOOL ToolBar;
	__declspec(property(get=GetOffline,put=PutOffline)) BOOL Offline;
	__declspec(property(get=GetSilent,put=PutSilent)) BOOL Silent;
	__declspec(property(get=GetFullScreen,put=PutFullScreen)) BOOL FullScreen;
	__declspec(property(get=GetStatusBar,put=PutStatusBar)) BOOL StatusBar;
	__declspec(property(get=GetLeft,put=PutLeft)) LONG Left;
	__declspec(property(get=GetTop,put=PutTop)) LONG Top;
	__declspec(property(get=GetWidth,put=PutWidth)) LONG Width;
	__declspec(property(get=GetHeight,put=PutHeight)) LONG Height;
	__declspec(property(get=GetDocument)) IDispatchPtr Document;

	BOOL CanBack() const
	{
		return m_bState[back];
	}

	BOOL CanForward() const
	{
		return m_bState[forward];
	}
	
	void Quit()
	{
		ATLASSERT(m_pBrowser);
		m_pBrowser->Quit();
	}
	
	void PutAddressBar(BOOL bNewValue)
	{
		ATLASSERT(m_pBrowser);
		m_pBrowser->put_AddressBar(bNewValue ? VARIANT_TRUE : VARIANT_FALSE);
	}
	BOOL GetAddressBar()
	{
		ATLASSERT(m_pBrowser);
		VARIANT_BOOL bResult;
		m_pBrowser->get_AddressBar(&bResult);
		return bResult ? TRUE : FALSE;
	}
	IDispatchPtr GetApplication()
	{
		ATLASSERT(m_pBrowser);
		IDispatchPtr pDispatch;
		m_pBrowser->get_Application(&pDispatch);
		return pDispatch;
	}
	BOOL GetBusy()
	{
		ATLASSERT(m_pBrowser);
		VARIANT_BOOL bResult;
		m_pBrowser->get_Busy(&bResult);
		return bResult ? TRUE : FALSE;
	}
	CString GetFullName() const
	{
		ATLASSERT(m_pBrowser);
		CComBSTR szResult;
		m_pBrowser->get_FullName(&szResult);
		return szResult;
	}
	CString GetLocationName() const
	{
		ATLASSERT(m_pBrowser);
		CComBSTR szResult;
		m_pBrowser->get_LocationName(&szResult);
		return szResult;
	}
	CString GetLocationURL() const
	{
		ATLASSERT(m_pBrowser);
		CComBSTR szResult;
		m_pBrowser->get_LocationURL(&szResult);
		return CString(szResult);
	}
	void PutRegisterAsBrowser(BOOL bNewValue)
	{
		ATLASSERT(m_pBrowser);
		m_pBrowser->put_RegisterAsBrowser(bNewValue ? VARIANT_TRUE : VARIANT_FALSE);
	}
	BOOL GetRegisterAsBrowser()
	{
		ATLASSERT(m_pBrowser);
		VARIANT_BOOL bResult;
		m_pBrowser->get_RegisterAsBrowser(&bResult);
		return bResult ? TRUE : FALSE;
	}
	void PutRegisterAsDropTarget(BOOL bNewValue)
	{
		ATLASSERT(m_pBrowser);
		m_pBrowser->put_RegisterAsDropTarget(bNewValue ? VARIANT_TRUE : VARIANT_FALSE);
	}
	BOOL GetRegisterAsDropTarget()
	{
		ATLASSERT(m_pBrowser);
		VARIANT_BOOL bResult;
		m_pBrowser->get_RegisterAsDropTarget(&bResult);
		return bResult ? TRUE : FALSE;
	}
	void PutTheaterMode(BOOL bNewValue)
	{
		ATLASSERT(m_pBrowser);
		m_pBrowser->put_TheaterMode(bNewValue ? VARIANT_TRUE : VARIANT_FALSE);
	}
	BOOL GetTheaterMode()
	{
		ATLASSERT(m_pBrowser);
		VARIANT_BOOL bResult;
		m_pBrowser->get_TheaterMode(&bResult);
		return bResult ? TRUE : FALSE;
	}
	void PutVisible(BOOL bNewValue)
	{
		ATLASSERT(m_pBrowser);
		m_pBrowser->put_Visible(bNewValue ? VARIANT_TRUE : VARIANT_FALSE);
	}
	BOOL GetVisible()
	{
		ATLASSERT(m_pBrowser);
		VARIANT_BOOL bResult;
		m_pBrowser->get_Visible(&bResult);
		return bResult ? TRUE : FALSE;
	}
	void PutMenuBar(BOOL bNewValue)
	{
		ATLASSERT(m_pBrowser);
		m_pBrowser->put_MenuBar(bNewValue ? VARIANT_TRUE : VARIANT_FALSE);
	}
	BOOL GetMenuBar()
	{
		ATLASSERT(m_pBrowser);
		VARIANT_BOOL bResult;
		m_pBrowser->get_MenuBar(&bResult);
		return bResult ? TRUE : FALSE;
	}
	void PutToolBar(int nNewValue)
	{
		ATLASSERT(m_pBrowser);
		m_pBrowser->put_ToolBar(nNewValue);
	}
	BOOL GetToolBar()
	{
		ATLASSERT(m_pBrowser);
		VARIANT_BOOL bResult;
		m_pBrowser->get_ToolBar(&bResult);
		return bResult ? TRUE : FALSE;
	}
	void PutOffline(BOOL bNewValue)
	{
		ATLASSERT(m_pBrowser);
		m_pBrowser->put_Offline(bNewValue ? VARIANT_TRUE : VARIANT_FALSE);
	}
	BOOL GetOffline()
	{
		ATLASSERT(m_pBrowser);
		VARIANT_BOOL bResult;
		m_pBrowser->get_Offline(&bResult);
		return bResult ? TRUE : FALSE;
	}
	void PutSilent(BOOL bNewValue)
	{
		ATLASSERT(m_pBrowser);
		m_pBrowser->put_Silent(bNewValue ? VARIANT_TRUE : VARIANT_FALSE);
	}
	BOOL GetSilent()
	{
		ATLASSERT(m_pBrowser);
		VARIANT_BOOL bResult;
		m_pBrowser->get_Silent(&bResult);
		return bResult ? TRUE : FALSE;
	}
	void PutFullScreen(BOOL bNewValue)
	{
		ATLASSERT(m_pBrowser);
		m_pBrowser->put_FullScreen(bNewValue ? VARIANT_TRUE : VARIANT_FALSE);
	}
	BOOL GetFullScreen()
	{
		ATLASSERT(m_pBrowser);
		VARIANT_BOOL bResult;
		m_pBrowser->get_FullScreen(&bResult);
		return bResult ? TRUE : FALSE;
	}
	void PutStatusBar(BOOL bNewValue)
	{
		ATLASSERT(m_pBrowser);
		m_pBrowser->put_StatusBar(bNewValue ? VARIANT_TRUE : VARIANT_FALSE); 
	}
	BOOL GetStatusBar()
	{
		ATLASSERT(m_pBrowser);
		VARIANT_BOOL bResult;
		m_pBrowser->get_StatusBar(&bResult);
		return bResult ? TRUE : FALSE;
	}
	void PutLeft(LONG nNewValue)
	{
		ATLASSERT(m_spBrowser);
		m_pBrowser->put_Left(nNewValue);
	}
	LONG GetLeft()
	{
		ATLASSERT(m_pBrowser);
		LONG nResult;
		m_pBrowser->get_Left(&bResult);
		return nResult;
	}
	void PutTop(LONG nNewValue)
	{
		ATLASSERT(m_pBrowser);
		m_pBrowser->put_Top(nNewValue);
	}
	LONG GetTop()
	{
		ATLASSERT(m_pBrowser);
		LONG nResult;
		m_pBrowser->get_Top(&bResult);
		return nResult;
	}
	void PutWidth(LONG nNewValue)
	{
		ATLASSERT(m_pBrowser);
		m_pBrowser->put_Width(nNewValue);
	}
	LONG GetWidth()
	{
		ATLASSERT(m_pBrowser);
		LONG nResult;
		m_pBrowser->get_Width(&bResult);
		return nResult;
	}
	void PutHeight(LONG nNewValue)
	{
		ATLASSERT(m_pBrowser);
		m_pBrowser->put_Height(nNewValue);
	}
	LONG GetHeight()
	{
		ATLASSERT(m_pBrowser);
		LONG nResult;
		m_pBrowser->get_Height(&bResult);
		return nResult;
	}
	IDispatchPtr GetDocument()
	{
		ATLASSERT(m_pBrowser);
		IDispatchPtr pDispatch;
		m_pBrowser->get_Document(&pDispatch);
		return pDispatch;
	}
	IHTMLDocument2* GetHtmlDocument() 
	{
		IHTMLDocument2 *document = NULL;
		if (m_pBrowser != NULL) 
		{

			// get browser document's dispatch interface

			IDispatch *document_dispatch = NULL;

			HRESULT hr = m_pBrowser->get_Document(&document_dispatch);

			if (SUCCEEDED(hr) && (document_dispatch != NULL)) 
			{

				// get the actual document interface

				hr = document_dispatch->QueryInterface(IID_IHTMLDocument2,
					(void **)&document);

				// release dispatch interface

				document_dispatch->Release();

			}

		}

		return document;
	}
	IHTMLDocument3* GetHtmlDocument3() 
	{
		IHTMLDocument3 *document = NULL;
		if (m_pBrowser != NULL) 
		{

			// get browser document's dispatch interface

			IDispatch *document_dispatch = NULL;

			HRESULT hr = m_pBrowser->get_Document(&document_dispatch);

			if (SUCCEEDED(hr) && (document_dispatch != NULL)) 
			{

				// get the actual document interface

				hr = document_dispatch->QueryInterface(IID_IHTMLDocument3,
					(void **)&document);

				// release dispatch interface

				document_dispatch->Release();

			}

		}

		return document;
	}
	HRESULT PutProperty(LPCTSTR szProperty,const VARIANT& vtValue)
	{
		ATLASSERT(m_pBrowser);
		USES_CONVERSION;
		return m_pBrowser->PutProperty(CComBSTR(szProperty),vtValue);
	}
	CComVariant GetProperty(LPCTSTR szProperty)
	{
		ATLASSERT(m_pBrowser);
		CComDispatchDriver pDriver(m_pBrowser);
		ATLASSERT(pDriver);
		CComVariant vtResult;
		pDriver.GetPropertyByName(CComBSTR(szProperty),&vtResult);
		return vtResult;
	}
	
	// Methods
	HRESULT ClientToWindow(LPPOINT pPoint)
	{
		ATLASSERT(m_pBrowser);
		ATLASSERT(pPoint);
		return m_pBrowser->ClientToWindow(&(pPoint->x),&(pPoint->y));
	}
	HRESULT ExecWB(OLECMDID nCmd,OLECMDEXECOPT nCmdOptions,VARIANT* pvInput=NULL,VARIANT* pvOutput=NULL)
	{
		ATLASSERT(m_pBrowser);
		return m_pBrowser->ExecWB(nCmd,nCmdOptions,pvInput,pvOutput);
	}
	HRESULT GoBack()
	{
		ATLASSERT(m_pBrowser);
		return m_pBrowser->GoBack();
	}
	HRESULT GoForward()
	{
		ATLASSERT(m_pBrowser);
		return m_pBrowser->GoForward();
	}
	HRESULT GoHome()
	{
		ATLASSERT(m_pBrowser);
		return m_pBrowser->GoHome();
	}
	HRESULT GoSearch()
	{
		ATLASSERT(m_pBrowser);
		return m_pBrowser->GoSearch();
	}
	HRESULT Navigate(LPCTSTR szURL,DWORD dwFlags=0,LPCTSTR szTargetFrameName=NULL,LPCVOID pPostData=NULL,DWORD dwPostDataLength=0,LPCTSTR szHeaders=NULL)
	{
		USES_CONVERSION;
		ATLASSERT(m_pBrowser);
		ATLASSERT(szURL);
		CComVariant vtTargetFrameName,vtPostData,vtHeaders;
		if (szTargetFrameName)
			vtTargetFrameName=szTargetFrameName;
		if (pPostData && dwPostDataLength>0)
		{
			vtPostData.ChangeType(VT_ARRAY|VT_UI1);
			SAFEARRAYBOUND Bound;
			Bound.cElements=dwPostDataLength;
			Bound.lLbound=0;
			vtPostData.parray=SafeArrayCreate(VT_UI1,1,&Bound);
			ATLASSERT(vtPostData.parray);
			if (vtPostData.parray==NULL)
				return E_OUTOFMEMORY;
			LPVOID pData;
			SafeArrayAccessData(vtPostData.parray,&pData);
			CopyMemory(pData,pPostData,dwPostDataLength);
			SafeArrayUnaccessData(vtPostData.parray);
		}
		if (szHeaders)
			vtHeaders=szHeaders;
		return m_pBrowser->Navigate(T2BSTR(szURL),&CComVariant((LONG)dwFlags),&vtTargetFrameName,&vtPostData,&vtHeaders);
	}
	HRESULT Navigate2(LPCTSTR szURL,DWORD dwFlags=0,LPCTSTR szTargetFrameName=NULL,LPCVOID pPostData=NULL,DWORD dwPostDataLength=0,LPCTSTR szHeaders=NULL)
	{
		ATLASSERT(m_pBrowser);
		ATLASSERT(szURL);
		CComVariant vtTargetFrameName,vtPostData,vtHeaders;
		if (szTargetFrameName)
			vtTargetFrameName=szTargetFrameName;
		if (pPostData && dwPostDataLength>0)
		{
			vtPostData.ChangeType(VT_ARRAY|VT_UI1);
			SAFEARRAYBOUND Bound;
			Bound.cElements=dwPostDataLength;
			Bound.lLbound=0;
			vtPostData.parray=SafeArrayCreate(VT_UI1,1,&Bound);
			ATLASSERT(vtPostData.parray);
			if (vtPostData.parray==NULL)
				return E_OUTOFMEMORY;
			LPVOID pData=NULL;
			SafeArrayAccessData(vtPostData.parray,&pData);
			ATLASSERT(pData);
			CopyMemory(pData,pPostData,dwPostDataLength);
			SafeArrayUnaccessData(vtPostData.parray);
		}
		if (szHeaders)
			vtHeaders=szHeaders;
		return m_pBrowser->Navigate2(&CComVariant(szURL),&CComVariant((LONG)dwFlags),&vtTargetFrameName,&vtPostData,&vtHeaders);
	}
	HRESULT Refresh()
	{
		ATLASSERT(m_pBrowser);
		return m_pBrowser->Refresh();
	}
	HRESULT Refresh2(LONG nLevel)
	{
		ATLASSERT(m_pBrowser);
		return m_pBrowser->Refresh2(CComVariant(nLevel));
	}
	HRESULT Stop()
	{
		ATLASSERT(m_pBrowser);
		return m_pBrowser->Stop();
	}
	OLECMDF QueryStatusWB(OLECMDID nCmd)
	{
		ATLASSERT(m_pBrowser);
		OLECMDF nResult;
		m_pBrowser->QueryStatusWB(nCmd,&nResult);
		return nResult;
	}
	
	HRESULT LoadFromResource(UINT nID) 
	{
		TCHAR szFilename[MAX_PATH];
		GetModuleFileName(_Module.GetModuleInstance(),szFilename,sizeof(szFilename)/sizeof(TCHAR));
		TCHAR szURL[4096];
		_stprintf(szURL,_T("res://%s/%d"),szFilename,nID);
		return Navigate(szURL);
	}
	HRESULT LoadFromResource(LPCTSTR szID) 
	{
		TCHAR szFilename[MAX_PATH];
		GetModuleFileName(_Module.GetModuleInstance(),szFilename,sizeof(szFilename)/sizeof(TCHAR));
		TCHAR szURL[4096];
		_stprintf(szURL,_T("res://%s/%s"),szFilename,szID);
		return Navigate(szURL);
	}
	HRESULT SetForeColor(LPCTSTR szColor) const
	{
		return ExecHelperSetVal(IDM_FORECOLOR, szColor);
	}

	HRESULT SetForeColor(int nColor) const
	{
		return ExecHelperSetVal(IDM_FORECOLOR, nColor, OLECMDF_SUPPORTED|OLECMDF_ENABLED);
	}

	HRESULT GetForeColor(int &nColor)
	{
		return ExecHelperGetVal(IDM_FORECOLOR, nColor, OLECMDF_ENABLED|OLECMDF_SUPPORTED);
	}

	HRESULT GetBackColor(int& nColor) const
	{
		return ExecHelperGetVal(IDM_BACKCOLOR, nColor, OLECMDF_ENABLED|OLECMDF_SUPPORTED);
	}
	static HRESULT OnMouseUp(LPVOID pVoid)
	{
		//::MessageBox(NULL,L"TT",L"TT",MB_OK);
		//m_MouseUp();
		HWND hWnd = GetActiveWindow();
		::SendMessage(hWnd,WM_LBUTTONUP,0,0);
		return 0L;
	}
	HRESULT SetBackColor(LPCTSTR szColor) const
	{
		return ExecHelperSetVal(IDM_BACKCOLOR, szColor, OLECMDF_ENABLED|OLECMDF_SUPPORTED);
	}

	HRESULT SetBackColor(int nColor) const
	{
		return ExecHelperSetVal(IDM_BACKCOLOR, nColor, OLECMDF_ENABLED|OLECMDF_SUPPORTED);
	}
	HRESULT SetCustomCursor(int hCur) const
	{
		return ExecHelperSetVal(IDM_SETCUSTOMCURSOR, hCur, OLECMDF_ENABLED|OLECMDF_SUPPORTED);
	}
	HRESULT SetDefaultComposeSettings(LPCSTR szFontName=NULL,
									  unsigned short nFontSize=3,
									  COLORREF crFontColor=0xFF000000,
									  COLORREF crFontBgColor=0xFF000000,
									  bool bBold = false,
									  bool bItalic = false,
									  bool bUnderline = false) const
	{

		HRESULT hr = ExecHelperSetVal(IDM_HTMLEDITMODE, true);
		if (FAILED(hr))
			return hr;

		CString strBuffer;
		TCHAR szFontColor[12];
		TCHAR szBgColor[12];
		if(crFontColor == 0xFF000000)
			szFontColor[0] = 0;
		else
			if (0 > _sntprintf(szFontColor, 12, _T("%d.%d.%d"), GetRValue(crFontColor),
					GetGValue(crFontColor), GetBValue(crFontColor)))
					return E_UNEXPECTED;

		if (crFontBgColor == 0xFF000000)
			szBgColor[0] = 0;
		else
			if (0 > _sntprintf(szBgColor, 12, _T("%d.%d.%d"), GetRValue(crFontBgColor),
					GetGValue(crFontBgColor), GetBValue(crFontBgColor)))
					return E_UNEXPECTED;

		_ATLTRY
		{
		strBuffer.Format(_T("%d,%d,%d,%d,%s,%s,%s"),
						bBold ? 1 : 0,
						bItalic ? 1 : 0,
						bUnderline ? 1 : 0,
						nFontSize,
						szFontColor,
						szBgColor,
						szFontName);
		}
		_ATLCATCHALL()
		{
			return E_UNEXPECTED;
		}
		return ExecHelperSetVal(IDM_COMPOSESETTINGS, (LPCTSTR)strBuffer);
	}

	HRESULT GetBlockFormat(CString& strFormat) const
	{
		return ExecHelperGetVal(IDM_BLOCKFMT, strFormat, OLECMDF_SUPPORTED|OLECMDF_ENABLED);
	}

	HRESULT SetBlockFormat(LPCTSTR szFormat) const
	{
		return ExecHelperSetVal(IDM_BLOCKFMT, szFormat);
	}

	HRESULT GetFontFace(CString& strFace) const
	{
		return ExecHelperGetVal(IDM_FONTNAME, strFace, OLECMDF_ENABLED|OLECMDF_SUPPORTED);
	}

	HRESULT SetFontFace(LPCTSTR szFace) const
	{
		return ExecHelperSetVal(IDM_FONTNAME, szFace);
	}

	HRESULT IE50Paste(LPCTSTR szData) const
	{
		return ExecHelperSetVal(IDM_IE50_PASTE, szData);
	}

	HRESULT GetBookMark(CString& strAnchor) const
	{
		return ExecHelperGetVal(IDM_BOOKMARK, strAnchor);
	}

	HRESULT SetBookMark(LPCTSTR szAnchorName) const
	{
		return ExecHelperSetVal(IDM_BOOKMARK, szAnchorName,OLECMDF_SUPPORTED);
	}

	HRESULT SetOverwriteMode(bool bMode) const
	{
		return ExecHelperSetVal(IDM_OVERWRITE, bMode);
	}

	HRESULT Is1DElement(bool& bValue) const
	{
		return ExecHelperGetVal(IDM_1D_ELEMENT, bValue);
	}

	HRESULT Is2DElement(bool& bValue) const
	{
		return ExecHelperGetVal(IDM_2D_ELEMENT, bValue);
	}

	HRESULT GetFontSize(short& nSize) const
	{
		return ExecHelperGetVal(IDM_FONTSIZE, nSize);
	}

	HRESULT SetFontSize(unsigned short size) const
	{
		return ExecHelperSetVal(IDM_FONTSIZE, (short)size);
	}

	HRESULT GetFrameZone(short& nZone) const
	{
		return ExecHelperGetVal(IDM_GETFRAMEZONE, nZone);
	}

	HRESULT SetCSSEditingLevel(short nLevel) const
	{
		return ExecHelperSetVal(IDM_CSSEDITING_LEVEL, nLevel, 0);
	}

	HRESULT HyperLink(LPCTSTR szUrl = NULL) const
	{
		if (szUrl)
			return ExecHelperSetVal(IDM_HYPERLINK, szUrl, OLECMDF_SUPPORTED,
									OLECMDEXECOPT_DONTPROMPTUSER);
		return ExecHelperNN(IDM_HYPERLINK, OLECMDF_SUPPORTED, OLECMDEXECOPT_DODEFAULT);
	}

	HRESULT Image(LPCTSTR szUrl = NULL) const
	{
		if (szUrl)
			return ExecHelperSetVal(IDM_IMAGE, szUrl, OLECMDF_SUPPORTED,
									OLECMDEXECOPT_DONTPROMPTUSER);
		return ExecHelperNN(IDM_IMAGE, OLECMDF_SUPPORTED, OLECMDEXECOPT_DODEFAULT);
	}

	HRESULT OrderList(LPCTSTR szId = NULL) const
	{
		return ExecHelperSetVal(IDM_ORDERLIST, szId);
	}

	HRESULT UnorderList(LPCTSTR szId = NULL) const
	{
		return ExecHelperSetVal(IDM_UNORDERLIST, szId);
	}

	HRESULT AddToGlyphTable(LPCTSTR szTag,
							LPCTSTR szImgUrl,
							unsigned short nTagType,
							unsigned short nAlignment,
							unsigned short nPosInfo,
							unsigned short nDirection,
							unsigned int nImgWidth,
							unsigned int nImgHeight) const
	{
		// Check Paramters
		if (!szTag ||
			!szImgUrl ||
			nTagType > 2 ||
			nAlignment > 3 ||
			nPosInfo > 3 ||
			nDirection > 4)
			return E_INVALIDARG;

		CString strGlyphEntry;
		_ATLTRY
		{
			strGlyphEntry.Format(_T("%%%%%s^^%%%%%s^^%%%%%d^^%%%%%d^^%%%%%d^^")
								 _T("%%%%%d^^%%%%%d^^%%%%%d^^%%%%%d^^%%%%%d^^**"),
								 szTag, szImgUrl, nTagType, nAlignment, nPosInfo,
								 nDirection, nImgWidth, nImgHeight, nImgWidth, nImgHeight);
		}
		_ATLCATCHALL()
		{
			return E_UNEXPECTED;
		}
		CComVariant vIn((LPCTSTR)strGlyphEntry);
		return ExecCommand(IDM_ADDTOGLYPHTABLE, OLECMDEXECOPT_DODEFAULT, &vIn);
	}

	HRESULT EmptyGlyphTable() const
	{
		return ExecHelperNN(IDM_EMPTYGLYPHTABLE);
	}

	HRESULT Button(LPCTSTR szId = NULL) const
	{
		return ExecHelperSetVal(IDM_BUTTON, szId);
	}

	HRESULT CheckBox(LPCTSTR szId = NULL) const
	{
		return ExecHelperSetVal(IDM_CHECKBOX, szId);
	}

	HRESULT DropDownBox(LPCTSTR szId = NULL) const
	{
		return ExecHelperSetVal(IDM_DROPDOWNBOX, szId);
	}

	HRESULT HorizontalLine(LPCTSTR szId = NULL) const
	{
		return ExecHelperSetVal(IDM_HORIZONTALLINE, szId);
	}

	HRESULT Iframe(LPCTSTR szId = NULL) const
	{
		return ExecHelperSetVal(IDM_IFRAME, szId);
	}

	HRESULT InsFieldSet(LPCTSTR szId = NULL) const
	{
		return ExecHelperSetVal(IDM_INSFIELDSET, szId);
	}

	HRESULT InsInputButton(LPCTSTR szId = NULL) const
	{
		return ExecHelperSetVal(IDM_INSINPUTBUTTON, szId);
	}

	HRESULT InsInputHidden(LPCTSTR szId = NULL) const
	{
		return ExecHelperSetVal(IDM_INSINPUTHIDDEN, szId);
	}

	HRESULT InsInputImage(LPCTSTR szId = NULL) const
	{
		return ExecHelperSetVal(IDM_INSINPUTIMAGE, szId);
	}

	HRESULT InsInputPassword(LPCTSTR szId = NULL) const
	{
		return ExecHelperSetVal(IDM_INSINPUTPASSWORD, szId);
	}

	HRESULT InsInputReset(LPCTSTR szId = NULL) const
	{
		return ExecHelperSetVal(IDM_INSINPUTRESET, szId);
	}

	HRESULT InsInputSubmit(LPCTSTR szId = NULL) const
	{
		return ExecHelperSetVal(IDM_INSINPUTSUBMIT, szId);
	}

	HRESULT InsInputUpload(LPCTSTR szId = NULL) const
	{
		return ExecHelperSetVal(IDM_INSINPUTUPLOAD, szId);
	}

	HRESULT ListBox(LPCTSTR szId = NULL) const
	{
		return ExecHelperSetVal(IDM_LISTBOX, szId);
	}

	HRESULT Marquee(LPCTSTR szId = NULL) const
	{
		return ExecHelperSetVal(IDM_MARQUEE, szId);
	}

	HRESULT Paragraph(LPCTSTR szId = NULL) const
	{
		return ExecHelperSetVal(IDM_PARAGRAPH, szId);
	}

	HRESULT RadioButton(LPCTSTR szId = NULL) const
	{
		return ExecHelperSetVal(IDM_RADIOBUTTON, szId);
	}

	HRESULT SaveAs(LPCTSTR szPath = NULL) const
	{
		if (szPath)
		{
			return ExecHelperSetVal(IDM_SAVEAS, szPath, OLECMDF_SUPPORTED,
									OLECMDEXECOPT_DONTPROMPTUSER);
		}
		else
		{
			return ExecHelperNN(IDM_SAVEAS, OLECMDF_SUPPORTED, OLECMDEXECOPT_DODEFAULT);
		}
	}

	HRESULT TextArea(LPCTSTR szId = NULL) const
	{
		return ExecHelperSetVal(IDM_TEXTAREA, szId);
	}

	HRESULT TextBox(LPCTSTR szId = NULL) const
	{
		return ExecHelperSetVal(IDM_TEXTBOX, szId);
	}

	HRESULT GetAbsolutePosition(bool &bCurValue) const
	{
		bCurValue = (QueryStatus(IDM_ABSOLUTE_POSITION) & OLECMDF_LATCHED) != 0;
		return S_OK;
	}

	HRESULT SetAbsolutePosition(bool bNewValue) const
	{
		return ExecHelperSetVal(IDM_ABSOLUTE_POSITION, bNewValue );
	}


	HRESULT Set2DPosition(bool bNewValue) const
	{
		return ExecHelperSetVal(IDM_2D_POSITION, bNewValue, 0);
	}

	HRESULT SetAtomicSelection(bool bNewValue) const
	{
		return ExecHelperSetVal(IDM_ATOMICSELECTION, bNewValue, 0);
	}

	HRESULT SetAutoURLDetectMode(bool bNewValue) const
	{
		return ExecHelperSetVal(IDM_AUTOURLDETECT_MODE, bNewValue, 0);
	}

	HRESULT SetDisableEditFocusUI(bool bNewValue) const
	{
		return ExecHelperSetVal(IDM_DISABLE_EDITFOCUS_UI, bNewValue, 0);
	}

	HRESULT SetIE5PasteMode(bool bNewValue) const
	{
		return ExecHelperSetVal(IDM_IE50_PASTE_MODE, bNewValue, 0);
	}

	HRESULT SetLiveResize(bool bNewValue) const
	{
		return ExecHelperSetVal(IDM_LIVERESIZE, bNewValue, 0);
	}

	HRESULT SetMultiSelect(bool bNewValue) const
	{
		return ExecHelperSetVal(IDM_MULTIPLESELECTION, bNewValue, 0);
	}

	HRESULT SetOverrideCursor(bool bNewValue) const
	{
		return ExecHelperSetVal(IDM_OVERRIDE_CURSOR, bNewValue, 0);
	}

	HRESULT SetRespectVisInDesign(bool bNewValue) const
	{
		return ExecHelperSetVal(IDM_RESPECTVISIBILITY_INDESIGN, bNewValue, 0);
	}

	HRESULT GetShowAlignedSiteTags(bool &bCurValue) const
	{
		bCurValue = (QueryStatus(IDM_SHOWALIGNEDSITETAGS) & OLECMDF_LATCHED) != 0;
		return S_OK;
	}

	HRESULT SetShowAlignedSiteTags(bool bNewValue) const
	{
		return ExecHelperSetVal(IDM_SHOWALIGNEDSITETAGS, bNewValue);
	}

	HRESULT GetShowAllTags(bool &bCurValue) const
	{
		bCurValue = (QueryStatus(IDM_SHOWALLTAGS) & OLECMDF_LATCHED) != 0;
		return S_OK;
	}

	HRESULT SetShowAllTags(bool bNewValue) const
	{
		return ExecHelperSetVal(IDM_SHOWALLTAGS, bNewValue);
	}

	HRESULT GetShowAreaTags(bool &bCurValue) const
	{
		bCurValue = (QueryStatus(IDM_SHOWAREATAGS) & OLECMDF_LATCHED) != 0;
		return S_OK;
	}

	HRESULT SetShowAreaTags(bool bNewValue) const
	{
		return ExecHelperSetVal(IDM_SHOWAREATAGS, bNewValue);
	}

	HRESULT GetShowCommentTags(bool &bCurValue) const
	{
		bCurValue = (QueryStatus(IDM_SHOWCOMMENTTAGS) & OLECMDF_LATCHED) != 0;
		return S_OK;
	}

	HRESULT SetShowCommentTags(bool bNewValue) const
	{
		return ExecHelperSetVal(IDM_SHOWCOMMENTTAGS, bNewValue);
	}

	HRESULT GetShowMiscTags(bool &bCurValue) const
	{
		bCurValue = (QueryStatus(IDM_SHOWMISCTAGS) & OLECMDF_LATCHED) != 0;
		return S_OK;
	}

	HRESULT SetShowMiscTags(bool bNewValue) const
	{
		return ExecHelperSetVal(IDM_SHOWMISCTAGS, bNewValue);
	}

	HRESULT GetShowScriptTags(bool &bCurValue) const
	{
		bCurValue = (QueryStatus(IDM_SHOWSCRIPTTAGS) & OLECMDF_LATCHED) != 0;
		return S_OK;
	}

	HRESULT SetShowScriptTags(bool bNewValue) const
	{
		return ExecHelperSetVal(IDM_SHOWSCRIPTTAGS, bNewValue);
	}

	HRESULT GetShowStyleTags(bool &bCurValue) const
	{
		bCurValue = (QueryStatus(IDM_SHOWSTYLETAGS) & OLECMDF_LATCHED) != 0;
		return S_OK;
	}

	HRESULT SetShowStyleTags(bool bNewValue) const
	{
		return ExecHelperSetVal(IDM_SHOWSTYLETAGS, bNewValue);
	}

	HRESULT GetShowUnknownTags(bool &bCurValue) const
	{
		bCurValue = (QueryStatus(IDM_SHOWUNKNOWNTAGS) & OLECMDF_LATCHED) != 0;
		return S_OK;
	}

	HRESULT SetShowUnknownTags(bool bNewValue) const
	{
		return ExecHelperSetVal(IDM_SHOWUNKNOWNTAGS, bNewValue);
	}

	HRESULT GetShowBRTags(bool &bCurValue) const
	{
		bCurValue = (QueryStatus(IDM_SHOWWBRTAGS) & OLECMDF_LATCHED) != 0;
		return S_OK;
	}

	HRESULT SetShowBRTags(bool bNewValue) const
	{
		return ExecHelperSetVal(IDM_SHOWWBRTAGS, bNewValue);
	}

	HRESULT PrintDocument() const
	{
		return ExecHelperNN(IDM_PRINT);
	}

	HRESULT PrintDocument(LPCTSTR szPrintTemplate) const
	{
		return ExecHelperSetVal(IDM_PRINT, szPrintTemplate);
	}

	HRESULT PrintDocument(bool bShowPrintDialog) const
	{
		return ExecHelperSetVal(IDM_PRINT, (short)(bShowPrintDialog ? 1 : 0));
	}

	HRESULT PrintPreview() const
	{
		return ExecHelperNN(IDM_PRINTPREVIEW);
	}

	HRESULT PrintPreview(LPCTSTR szPrintTemplate) const
	{
		return ExecHelperSetVal(IDM_PRINTPREVIEW, szPrintTemplate);
	}

	HRESULT Bold() const
	{
		return ExecHelperNN(IDM_BOLD);
	}

	HRESULT Copy() const
	{
		return ExecHelperNN(IDM_COPY);
	}

	HRESULT Cut() const
	{
		return ExecHelperNN(IDM_CUT);
	}

	HRESULT Delete() const
	{
		return ExecHelperNN(IDM_DELETE);
	}

	HRESULT Indent() const
	{
		return ExecHelperNN(IDM_INDENT);
	}

	HRESULT Italic() const
	{
		return ExecHelperNN(IDM_ITALIC);
	}

	HRESULT JustifyCenter() const
	{
		return ExecHelperNN(IDM_JUSTIFYCENTER);
	}

	HRESULT JustifyLeft() const
	{
		return ExecHelperNN(IDM_JUSTIFYLEFT);
	}

	HRESULT JustifyRight() const
	{
		return ExecHelperNN(IDM_JUSTIFYRIGHT);
	}

	HRESULT Outdent() const
	{
		return ExecHelperNN(IDM_OUTDENT);
	}

	HRESULT Paste() const
	{
		return ExecHelperNN(IDM_PASTE);
	}

	HRESULT RemoveFormat() const
	{
		return ExecHelperNN(IDM_REMOVEFORMAT);
	}

	HRESULT SelectAll() const
	{
		return ExecHelperNN(IDM_SELECTALL);
	}

	HRESULT Underline() const
	{
		return ExecHelperNN(IDM_UNDERLINE);
	}

	HRESULT Unlink() const
	{
		return ExecHelperNN(IDM_UNLINK);
	}

	HRESULT ClearSelection() const
	{
		return ExecHelperNN(IDM_CLEARSELECTION);
	}

	HRESULT Font() const
	{
		return ExecHelperNN(IDM_FONT);
	}

	HRESULT RefreshDocument() const
	{
		return ExecHelperNN(IDM_REFRESH, OLECMDF_SUPPORTED);
	}

	HRESULT UnBookmark() const
	{
		return ExecHelperNN(IDM_UNBOOKMARK);
	}
	HRESULT ExecCommand( long cmdID, long cmdExecOpt, VARIANT* pInVar=NULL, VARIANT* pOutVar=NULL) const
	{
		//const T* pT = static_cast<const T*>(this);
		::ATL::CComPtr<IHTMLDocument2> spDoc;
		HRESULT hr = E_FAIL;
		//spDoc = IHTMLDocument2 *document = NULL;
		if (m_pBrowser != NULL) 
		{

			// get browser document's dispatch interface

			IDispatch *document_dispatch = NULL;

			HRESULT hr = m_pBrowser->get_Document(&document_dispatch);

			if (SUCCEEDED(hr) && (document_dispatch != NULL)) 
			{

				// get the actual document interface

				hr = document_dispatch->QueryInterface(IID_IHTMLDocument2,
					(void **)&spDoc);

				// release dispatch interface

				document_dispatch->Release();

			}

		}
		if (spDoc)
		{
			CComQIPtr<IOleCommandTarget> spCmdTarg = spDoc;
			if (spCmdTarg)
			{
				hr = spCmdTarg->Exec(&CGID_MSHTML, cmdID, cmdExecOpt, pInVar , pOutVar);
			}
			else
				hr = E_NOINTERFACE;
		}
		return hr;
	}
	/*HRESULT ExecCommand(long cmdID, long cmdExecOpt, VARIANT* pInVar=NULL, VARIANT* pOutVar=NULL) const
	{
		return m_pBrowser->ExecWB( (OLECMDID)cmdID, (OLECMDEXECOPT)cmdExecOpt, 
					pInVar , pOutVar );
	}*/
	/*long QueryStatus(long cmdID) const
	{
		ATLASSERT(m_pBrowser != NULL);

		OLECMDF result;
		HRESULT hr = m_pBrowser->QueryStatusWB((OLECMDID)cmdID, &result);
		if(FAILED(hr))
			ATLASSERT(TRUE);
		;
		return result | OLECMDF_ENABLED;

	}*/
	long QueryStatus(long cmdID) const
	{
		const T* pT = static_cast<const T*>(this);
		::ATL::CComPtr<IHTMLDocument2> spDoc;
		HRESULT hr = E_FAIL;
		//spDoc = IHTMLDocument2 *document = NULL;
		if (m_pBrowser != NULL) 
		{

			// get browser document's dispatch interface

			IDispatch *document_dispatch = NULL;

			HRESULT hr = m_pBrowser->get_Document(&document_dispatch);

			if (SUCCEEDED(hr) && (document_dispatch != NULL)) 
			{

				// get the actual document interface

				hr = document_dispatch->QueryInterface(IID_IHTMLDocument2,
					(void **)&spDoc);

				// release dispatch interface

				document_dispatch->Release();

			}

		}
		if (spDoc)
		{
			CComQIPtr<IOleCommandTarget> spCmdTarg = spDoc;
			if (spCmdTarg)
			{
				OLECMD ocmd = {cmdID, 0};
				if (S_OK == spCmdTarg->QueryStatus(&CGID_MSHTML, 1, &ocmd, NULL))
					return ocmd.cmdf;
			}
		}
		// if an error occurred, returning 0 means the command is disabled
		return 0;
	}
	HRESULT ExecHelperNN(UINT nID,
						 long nMinSupportLevel = OLECMDF_SUPPORTED|OLECMDF_ENABLED,
						 long nExecOpt = OLECMDEXECOPT_DODEFAULT) const
	{
		HRESULT hr = E_FAIL;
		long lStatus = QueryStatus(nID);
		if ((lStatus & nMinSupportLevel) == nMinSupportLevel)
			hr = ExecCommand(nID, nExecOpt);
		return hr;
	}

	HRESULT ExecHelperSetVal(UINT nCmdID, 
							 LPCTSTR szID=NULL,
							 long nMinSupportLevel = OLECMDF_SUPPORTED|OLECMDF_ENABLED,
							 long nExecOpt = OLECMDEXECOPT_DODEFAULT) const
	{
		long lStatus = QueryStatus(nCmdID);
		if ((lStatus & nMinSupportLevel) == nMinSupportLevel)
		{
			if (szID)
			{
				CComVariant vName(szID);
				return ExecCommand(nCmdID, nExecOpt, &vName);
			}
			else
				return ExecCommand(nCmdID, nExecOpt);
		}
		return E_FAIL;
	}

	HRESULT ExecHelperSetVal(UINT nCmdID,
							 bool bValue,
							 long nMinSupportLevel = OLECMDF_SUPPORTED|OLECMDF_ENABLED,
							 long nExecOpt = OLECMDEXECOPT_DODEFAULT) const
	{
		HRESULT hr = E_FAIL;
		long lStatus = QueryStatus(nCmdID);
		if ((lStatus & nMinSupportLevel) == nMinSupportLevel)
		{
			CComVariant vIn(bValue);
			hr = ExecCommand(nCmdID, nExecOpt, &vIn);
		}
		return hr;
	}

	HRESULT ExecHelperSetVal(UINT nCmdID,
							 short nNewVal,
							 long nMinSupportLevel = OLECMDF_SUPPORTED|OLECMDF_ENABLED,
							 long nExecOpt = OLECMDEXECOPT_DODEFAULT) const
	{
		HRESULT hr = E_FAIL;
		long lStatus = QueryStatus(nCmdID);
		if ((lStatus & nMinSupportLevel) == nMinSupportLevel)
		{
			CComVariant vIn((short)nNewVal);
			hr = ExecCommand(nCmdID, nExecOpt, &vIn);
		}
		return hr;
	}

	HRESULT ExecHelperSetVal(UINT nCmdID,
							 int nNewVal,
							 long nMinSupportLevel = OLECMDF_SUPPORTED|OLECMDF_ENABLED,
							 long nExecOpt = OLECMDEXECOPT_DODEFAULT) const
	{
		HRESULT hr = E_FAIL;
		long lStatus = QueryStatus(nCmdID);
		if ((lStatus & nMinSupportLevel) == nMinSupportLevel)
		{
			CComVariant vIn((int)nNewVal);
			hr = ExecCommand(nCmdID, nExecOpt, &vIn);
		}
		return hr;
	}

	HRESULT ExecHelperGetVal(UINT nCmdID,
							 bool &bValue,
							 long nMinSupportLevel = OLECMDF_SUPPORTED,
							 long nExecOpt = OLECMDEXECOPT_DODEFAULT) const
	{
		HRESULT hr = E_FAIL;
		bValue = false;
		long lStatus = QueryStatus(nCmdID);
		if ((lStatus & nMinSupportLevel) == nMinSupportLevel)
		{
			CComVariant vOut;
			hr = ExecCommand(nCmdID, nExecOpt, NULL, &vOut);
			if (hr == S_OK)
			{
				switch(vOut.vt)
				{
				case VT_BOOL:
					bValue = vOut.boolVal == VARIANT_TRUE ? true : false;
					break;
				case VT_NULL:
				case VT_EMPTY:
					break;
				case VT_ERROR:
					hr = V_ERROR(&vOut);
					break;
				default:
					hr = E_UNEXPECTED;
					break;
				}
			}
		}
		return hr;
	}

	HRESULT ExecHelperGetVal(UINT nCmdID,
							 short &nValue,
							 long nMinSupportLevel = OLECMDF_SUPPORTED,
							 long nExecOpt = OLECMDEXECOPT_DODEFAULT) const
	{
		int nTempVal;
		HRESULT hr = ExecHelperGetVal(nCmdID, nTempVal, nMinSupportLevel, nExecOpt);
		if (hr == S_OK)
			nValue = (short)nTempVal;
		return hr;
	}


	HRESULT ExecHelperGetVal(UINT nCmdID,
							 int &nValue,
							 long nMinSupportLevel = OLECMDF_SUPPORTED,
							 long nExecOpt = OLECMDEXECOPT_DODEFAULT) const
	{
		HRESULT hr = E_FAIL;
		long lStatus = QueryStatus(nCmdID);
		nValue = 0;
		if ((lStatus & nMinSupportLevel) == nMinSupportLevel)
		{
			CComVariant vOut;
			hr = ExecCommand(nCmdID, nExecOpt, NULL, &vOut);
			if (hr == S_OK)
			{
				switch (vOut.vt)
				{
				case VT_I4:
					nValue = vOut.lVal;
					break;
				case VT_I2:
					nValue = vOut.iVal;
					break;
				case VT_EMPTY:
				case VT_NULL:
					break;
				case VT_ERROR:
					hr = V_ERROR(&vOut);
					break;
				default:
					hr = E_UNEXPECTED;
					break;
				}
			}
		}
		return hr;
	}

	HRESULT ExecHelperGetVal(UINT nCmdID,
							 CString& strValue,
							 long nMinSupportLevel = OLECMDF_SUPPORTED,
							 long nExecOpt = OLECMDEXECOPT_DODEFAULT) const
	{
		HRESULT hr = E_FAIL;
		CComVariant vaRet;
		strValue.Empty();
		long lStatus = QueryStatus(nCmdID);
		if ((lStatus & nMinSupportLevel) == nMinSupportLevel)
		{
			hr = ExecCommand(nCmdID, nExecOpt, NULL, &vaRet);
			if (hr == S_OK)
			{
				switch(vaRet.vt)
				{
				case VT_BSTR:
					{
					CW2T szVal(vaRet.bstrVal);
					strValue = szVal;
					}
					break;
				case VT_NULL:
				case VT_EMPTY:
					break;
				case VT_ERROR:
					hr = V_ERROR(&vaRet);
					break;
				default:
					hr = E_UNEXPECTED;
					break;
				}
			}
		}
		return hr;
	}
	void SetDocumentHTML(LPCTSTR szHTML) 
	{
		IHTMLDocument2 *document = GetHtmlDocument();
		
		if (document != NULL) {

			// construct text to be written to browser as SAFEARRAY

			SAFEARRAY *safe_array = SafeArrayCreateVector(VT_VARIANT,0,1);
			
			VARIANT	*variant;
			
			SafeArrayAccessData(safe_array,(LPVOID *)&variant);
			
			variant->vt      = VT_BSTR;
			variant->bstrVal = CString(szHTML).AllocSysString();
			
			SafeArrayUnaccessData(safe_array);

			// write SAFEARRAY to browser document

			document->write(safe_array);
			
			document->Release();
			document = NULL;

		}
	}
	void Clear()
	{
		if (m_pBrowser != NULL) {

			// if document interface available, close/re-open document to clear display

			IHTMLDocument2	*document	= GetHtmlDocument();
			HRESULT			hr			= S_OK;

			if (document != NULL) {

				// close and re-open document to empty contents

				document->close();

				VARIANT		open_name;
				VARIANT		open_features;
				VARIANT		open_replace;
				IDispatch	*open_window	= NULL;

				::VariantInit(&open_name);

				open_name.vt      = VT_BSTR;
				open_name.bstrVal = ::SysAllocString(L"_self");

				::VariantInit(&open_features);
				::VariantInit(&open_replace);

				hr = document->open(::SysAllocString(L"text/html"),
					open_name,
					open_features,
					open_replace,
					&open_window);

				if (hr == S_OK) {
					Refresh();
				}

				if (open_window != NULL) {
					open_window->Release();
				}

			}

			// otherwise, navigate to about:blank and wait for document ready

			else {

				Navigate(_T("about:blank"));

				IHTMLDocument2 *document = NULL;
				HRESULT			hr       = S_OK;

				while ((document == NULL) && (hr == S_OK)) {

					Sleep(0);

					IDispatch *document_dispatch = NULL;

					hr = m_pBrowser->get_Document(&document_dispatch);

					// if dispatch interface available, retrieve document interface

					if (SUCCEEDED(hr) && (document_dispatch != NULL)) {

						// retrieve document interface

						hr = document_dispatch->QueryInterface(IID_IHTMLDocument2,(void **)&document);

						document_dispatch->Release();

					}

				}

				if (document != NULL) {
					document->Release();	
				}

			}

		}
	}
protected:
	enum
	{
		back = 0,
		forward
	};
	CComPtr<IWebBrowser2> m_pBrowser;
	BOOL m_bState[2];
	
private:
	void __stdcall __SetSecureLockIcon(long nSecureLockIcon)
	{
		T* pT = static_cast<T*>(this);
		pT->OnSetSecureLockIcon(nSecureLockIcon);
	}
	
	void __stdcall __NavigateError(IDispatch* pDisp, VARIANT* pvURL, VARIANT* pvTargetFrameName, VARIANT* pvStatusCode, VARIANT_BOOL* pbCancel)
	{
		T* pT = static_cast<T*>(this);
		ATLASSERT(V_VT(pvURL) == VT_BSTR);
		ATLASSERT(V_VT(pvTargetFrameName) == VT_BSTR);
		ATLASSERT(V_VT(pvStatusCode) == (VT_I4));
		ATLASSERT(pbCancel != NULL);
		*pbCancel=pT->OnNavigateError(pDisp,V_BSTR(pvURL),V_BSTR(pvTargetFrameName),V_I4(pvStatusCode));
	}
	
	void __stdcall __PrivacyImpactedStateChange(VARIANT_BOOL bImpacted)
	{
		T* pT = static_cast<T*>(this);
		pT->OnPrivacyImpactedStateChange(bImpacted);
	}
	
	void __stdcall __StatusTextChange(BSTR szText)
	{
		T* pT = static_cast<T*>(this);
		pT->OnStatusTextChange(szText);
	}
	
	void __stdcall __ProgressChange(long nProgress, long nProgressMax)
	{
		T* pT = static_cast<T*>(this);
		pT->OnProgressChange(nProgress, nProgressMax);
	}
	
	void __stdcall __CommandStateChange(long nCommand, VARIANT_BOOL bEnable)
	{
		T* pT = static_cast<T*>(this);
		pT->OnCommandStateChange(nCommand, (bEnable==VARIANT_TRUE) ? TRUE : FALSE);
	}
	
	void __stdcall __DownloadBegin()
	{
		T* pT = static_cast<T*>(this);
		pT->OnDownloadBegin();
	}
	
	void __stdcall __DownloadComplete()
	{
		T* pT = static_cast<T*>(this);
		pT->OnDownloadComplete();
	}
	
	void __stdcall __TitleChange(BSTR szText)
	{
		T* pT = static_cast<T*>(this);
		pT->OnTitleChange(szText);
	}
	
	void __stdcall __NavigateComplete2(IDispatch* pDisp, VARIANT* pvURL)
	{
		T* pT = static_cast<T*>(this);
		ATLASSERT(V_VT(pvURL) == VT_BSTR);
		pT->OnNavigateComplete2(pDisp, V_BSTR(pvURL));
	}
	
	void __stdcall __BeforeNavigate2(IDispatch* pDisp, VARIANT* pvURL, VARIANT* pvFlags, VARIANT* pvTargetFrameName, VARIANT* pvPostData, VARIANT* pvHeaders, VARIANT_BOOL* pbCancel)
	{
		T* pT = static_cast<T*>(this);
		ATLASSERT(V_VT(pvURL) == VT_BSTR);
		ATLASSERT(V_VT(pvTargetFrameName) == VT_BSTR);
		ATLASSERT(V_VT(pvPostData) == (VT_VARIANT | VT_BYREF));
		ATLASSERT(V_VT(pvHeaders) == VT_BSTR);
		ATLASSERT(pbCancel != NULL);
		
		VARIANT* vtPostedData = V_VARIANTREF(pvPostData);
		CSimpleArray<BYTE> pArray;
		if (V_VT(vtPostedData) & VT_ARRAY)
		{
			ATLASSERT(V_ARRAY(vtPostedData)->cDims == 1 && V_ARRAY(vtPostedData)->cbElements == 1);
			long nLowBound=0,nUpperBound=0;
			SafeArrayGetLBound(V_ARRAY(vtPostedData), 1, &nLowBound);
			SafeArrayGetUBound(V_ARRAY(vtPostedData), 1, &nUpperBound);
			DWORD dwSize=nUpperBound+1-nLowBound;
			LPVOID pData=NULL;
			SafeArrayAccessData(V_ARRAY(vtPostedData),&pData);
			ATLASSERT(pData);
			
			pArray.m_nSize=pArray.m_nAllocSize=dwSize;
			pArray.m_aT=(BYTE*)malloc(dwSize);
			ATLASSERT(pArray.m_aT);
			CopyMemory(pArray.GetData(), pData, dwSize);
			SafeArrayUnaccessData(V_ARRAY(vtPostedData));
		}
		*pbCancel=pT->OnBeforeNavigate2(pDisp, V_BSTR(pvURL), V_I4(pvFlags), V_BSTR(pvTargetFrameName), pArray, V_BSTR(pvHeaders)) ? VARIANT_TRUE : VARIANT_FALSE;
	}
	
	void __stdcall __PropertyChange(BSTR szProperty)
	{
		T* pT = static_cast<T*>(this);
		pT->OnPropertyChange(szProperty);
	}
	
	void __stdcall __NewWindow2(IDispatch** ppDisp, VARIANT_BOOL* pbCancel)
	{
		T* pT = static_cast<T*>(this);
		*pbCancel = pT->OnNewWindow2(ppDisp) ? VARIANT_TRUE : VARIANT_FALSE;
	}
	
	void __stdcall __DocumentComplete(IDispatch* pDisp, VARIANT* pvURL)
	{
		T* pT = static_cast<T*>(this);
		ATLASSERT(V_VT(pvURL) == VT_BSTR);
		pT->OnDocumentComplete(pDisp, V_BSTR(pvURL));
	}
	
	void __stdcall __OnQuit()
	{
		T* pT = static_cast<T*>(this);
		pT->OnQuit();
	}
	
	void __stdcall __OnVisible(VARIANT_BOOL bVisible)
	{
		T* pT = static_cast<T*>(this);
		pT->OnVisible(bVisible == VARIANT_TRUE ? TRUE : FALSE);
	}
	
	void __stdcall __OnToolBar(VARIANT_BOOL bToolBar)
	{
		T* pT = static_cast<T*>(this);
		pT->OnToolBar(bToolBar == VARIANT_TRUE ? TRUE : FALSE);
	}
	
	void __stdcall __OnMenuBar(VARIANT_BOOL bMenuBar)
	{
		T* pT = static_cast<T*>(this);
		pT->OnMenuBar(bMenuBar == VARIANT_TRUE ? TRUE : FALSE);
	}
	
	void __stdcall __OnStatusBar(VARIANT_BOOL bStatusBar)
	{
		T* pT = static_cast<T*>(this);
		pT->OnStatusBar(bStatusBar == VARIANT_TRUE ? TRUE : FALSE);
	}
	
	void __stdcall __OnFullScreen(VARIANT_BOOL bFullScreen)
	{
		T* pT = static_cast<T*>(this);
		pT->OnFullScreen(bFullScreen == VARIANT_TRUE ? TRUE : FALSE);
	}
	
	void __stdcall __OnTheaterMode(VARIANT_BOOL bTheaterMode)
	{
		T* pT = static_cast<T*>(this);
		pT->OnTheaterMode(bTheaterMode == VARIANT_TRUE ? TRUE : FALSE);
	}
	
	/*
	void __stdcall __FileDownload(VARIANT_BOOL* pbCancel)
	{
		T* pT = static_cast<T*>(this);
		*pbCancel = pT->OnFileDownload() ? VARIANT_TRUE : VARIANT_FALSE;
	}
	*/
	/*
	void __stdcall __WindowClosing(VARIANT_BOOL bChildWindow,VARIANT_BOOL* pbCancel)
	{
		T* pT = static_cast<T*>(this);
		*pbCancel=pT->OnWindowClosing(bChildWindow ? TRUE : FALSE);
	}
	*/
};

__declspec(selectany) _ATL_FUNC_INFO CWebBrowser2EventsBase::StatusTextChangeStruct = {CC_STDCALL, VT_EMPTY, 1, {VT_BSTR}};
__declspec(selectany) _ATL_FUNC_INFO CWebBrowser2EventsBase::TitleChangeStruct = {CC_STDCALL, VT_EMPTY, 1, {VT_BSTR}};
__declspec(selectany) _ATL_FUNC_INFO CWebBrowser2EventsBase::PropertyChangeStruct = {CC_STDCALL, VT_EMPTY, 1, {VT_BSTR}};
__declspec(selectany) _ATL_FUNC_INFO CWebBrowser2EventsBase::DownloadBeginStruct = {CC_STDCALL, VT_EMPTY, 0, {NULL}};
__declspec(selectany) _ATL_FUNC_INFO CWebBrowser2EventsBase::DownloadCompleteStruct = {CC_STDCALL, VT_EMPTY, 0, {NULL}};
__declspec(selectany) _ATL_FUNC_INFO CWebBrowser2EventsBase::OnQuitStruct = {CC_STDCALL, VT_EMPTY, 0, {NULL}};
__declspec(selectany) _ATL_FUNC_INFO CWebBrowser2EventsBase::NewWindow2Struct = {CC_STDCALL, VT_EMPTY, 2, {VT_BYREF|VT_BOOL,VT_BYREF|VT_DISPATCH}}; 
__declspec(selectany) _ATL_FUNC_INFO CWebBrowser2EventsBase::CommandStateChangeStruct = {CC_STDCALL, VT_EMPTY, 2, {VT_I4,VT_BOOL}};
__declspec(selectany) _ATL_FUNC_INFO CWebBrowser2EventsBase::BeforeNavigate2Struct = {CC_STDCALL, VT_EMPTY, 7, {VT_DISPATCH,VT_BYREF|VT_VARIANT,VT_BYREF|VT_VARIANT,VT_BYREF|VT_VARIANT,VT_BYREF|VT_VARIANT,VT_BYREF|VT_VARIANT,VT_BYREF|VT_BOOL}};
__declspec(selectany) _ATL_FUNC_INFO CWebBrowser2EventsBase::ProgressChangeStruct = {CC_STDCALL, VT_EMPTY, 2, {VT_I4,VT_I4}};
__declspec(selectany) _ATL_FUNC_INFO CWebBrowser2EventsBase::NavigateComplete2Struct = {CC_STDCALL, VT_EMPTY, 2, {VT_DISPATCH, VT_BYREF|VT_VARIANT}};
__declspec(selectany) _ATL_FUNC_INFO CWebBrowser2EventsBase::DocumentComplete2Struct = {CC_STDCALL, VT_EMPTY, 2, {VT_DISPATCH, VT_BYREF|VT_VARIANT}};
__declspec(selectany) _ATL_FUNC_INFO CWebBrowser2EventsBase::OnVisibleStruct = {CC_STDCALL, VT_EMPTY, 1, {VT_BOOL}};
__declspec(selectany) _ATL_FUNC_INFO CWebBrowser2EventsBase::OnToolBarStruct = {CC_STDCALL, VT_EMPTY, 1, {VT_BOOL}};
__declspec(selectany) _ATL_FUNC_INFO CWebBrowser2EventsBase::OnMenuBarStruct = {CC_STDCALL, VT_EMPTY, 1, {VT_BOOL}};
__declspec(selectany) _ATL_FUNC_INFO CWebBrowser2EventsBase::OnStatusBarStruct = {CC_STDCALL, VT_EMPTY, 1, {VT_BOOL}};
__declspec(selectany) _ATL_FUNC_INFO CWebBrowser2EventsBase::OnFullScreenStruct = {CC_STDCALL, VT_EMPTY, 1, {VT_BOOL}};
__declspec(selectany) _ATL_FUNC_INFO CWebBrowser2EventsBase::OnTheaterModeStruct = {CC_STDCALL, VT_EMPTY, 1, {VT_BOOL}};
__declspec(selectany) _ATL_FUNC_INFO CWebBrowser2EventsBase::SetSecureLockIconStruct = {CC_STDCALL, VT_EMPTY, 1, {VT_I4}};
__declspec(selectany) _ATL_FUNC_INFO CWebBrowser2EventsBase::NavigateErrorStruct = {CC_STDCALL, VT_EMPTY, 5, {VT_BYREF|VT_BOOL,VT_BYREF|VT_VARIANT,VT_BYREF|VT_VARIANT,VT_BYREF|VT_VARIANT,VT_BYREF|VT_DISPATCH}};
__declspec(selectany) _ATL_FUNC_INFO CWebBrowser2EventsBase::PrivacyImpactedStateChangeStruct = {CC_STDCALL, VT_EMPTY, 1, {VT_BOOL}};
//__declspec(selectany) _ATL_FUNC_INFO CWebBrowser2EventsBase::FileDownloadStruct = {CC_STDCALL, VT_EMPTY, 1, {VT_BYREF|VT_BOOL}};
//__declspec(selectany) _ATL_FUNC_INFO CWebBrowser2EventsBase::WindowClosingStruct = {CC_STDCALL, VT_EMPTY, 2, {VT_BYREF|VT_BOOL,VT_BOOL}};

#endif
